/*
 * Created by SharpDevelop.
 * User: Tivadar Papai
 * Date: 8/27/2007
 * Time: 3:16 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;

namespace RoverStudio.Math
{
	/// <summary>
	/// Description of Vector3D.
	/// </summary>
	public class Vector3D
	{

        private double x;

        public double X
        {
            get { return x; }
            set { x = value; }
        }

        private double y;

        public double Y
        {
            get { return y; }
            set { y = value; }
        }

        private double z;

        public double Z
        {
            get { return z; }
            set { z = value; }
        }

        public Vector3D() : this(0, 0, 0) { }
        public Vector3D(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public Vector3D(Vector3D v)
        {
            this.x = v.x;
            this.y = v.y;
            this.z = v.z;
        }

        public static Vector3D operator ^(Vector3D operand1, Vector3D operand2)
        {
            return new Vector3D(operand1.y * operand2.z - operand2.y * operand1.z, operand1.z * operand2.x - operand2.z * operand1.x, operand1.x * operand2.y - operand2.x * operand1.y);
        }

        public static double operator *(Vector3D operand1, Vector3D operand2)
        {
            return operand1.x * operand2.x + operand1.y * operand2.y + operand1.z * operand2.z;
        }

        public static Vector3D operator *(Vector3D operand1, double operand2)
        {
            return new Vector3D(operand1.x * operand2, operand1.y * operand2, operand1.z * operand2);
        }

        public static Vector3D operator /(Vector3D operand1, double operand2)
        {
            return new Vector3D(operand1.x / operand2, operand1.y / operand2, operand1.z / operand2);
        }

        public static Vector3D operator *(double operand1, Vector3D operand2)
        {
            return new Vector3D(operand1 * operand2.x, operand1 * operand2.y, operand1 * operand2.z);
        }

        public static Vector3D operator +(Vector3D operand1, Vector3D operand2)
        {
            return new Vector3D(operand1.x + operand2.x, operand1.y + operand2.y, operand1.z + operand2.z);
        }

        public static Vector3D operator -(Vector3D operand1, Vector3D operand2)
        {
            return new Vector3D(operand1.x - operand2.x, operand1.y - operand2.y, operand1.z - operand2.z);
        }

        public Vector3D Scale(double scale)
        {
            this.x *= scale;
            this.y *= scale;
            this.z *= scale;
            return this;
        }

        public Vector3D Shift(Vector3D shift)
        {
            this.x += shift.x;
            this.y += shift.y;
            this.z += shift.z;
            return this;

        }

        public double Length()
        {
            return System.Math.Sqrt(x * x + y * y + z * z);
        }

        public double Length2D()
        {
            return System.Math.Sqrt(x * x + y * y);
        }
        public Vector3D GetNormalizedVector3D()
        {
            double length = this.Length();
            return new Vector3D(this.x / length, this.y / length, this.z / length);
        }

        public Vector3D FlipVertical()
        {
            return new Vector3D(-this.x, this.y, this.z);
        }

        public Vector3D FlipHorizontal()
        {
            return new Vector3D(this.x, -this.y, this.z);
        }


        public static explicit operator Vector2D(Vector3D vector)
        {
            return new Vector2D(vector.x, vector.y);
        }

        public static Vector3D operator -(Vector3D vector)
        {
            return (-1) * vector;
        }

        public override string ToString()
        {
            return String.Format("({0}; {1}; {2})", x, y, z);
        }

	}
}
